package main

import (
	"github.com/google/gopacket"
	"net"
	"github.com/google/gopacket/layers"
	"fmt"
	"syscall"
)

func main() {
	rawBytes := []byte{10, 20, 30}
	options := gopacket.SerializeOptions{}

	//修改IP层信息,不过好像还有点问题
	ipLayer := &layers.IPv4{
		Version:4,
		TTL:128,
		Length:0x50,
		SrcIP: net.IP{127, 0, 0, 1},
		DstIP: net.IP{8, 8, 8, 8},
		Protocol:layers.IPProtocolIPv4,
		Flags:layers.IPv4DontFragment,
		TOS:1<<3,

	}

	//修改Ethernet层的信息
	ethernetLayer := &layers.Ethernet{
		SrcMAC: net.HardwareAddr{0xFF, 0xAA, 0xFA, 0xAA, 0xFF, 0xAA},
		DstMAC: net.HardwareAddr{0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD},
		EthernetType:layers.EthernetTypeIPv4,
	}
	tcpLayer := &layers.TCP{
		SrcPort: layers.TCPPort(4321),
		DstPort: layers.TCPPort(80),
	}
	// And create the packet with the layers
	buffer := gopacket.NewSerializeBuffer()
	gopacket.SerializeLayers(buffer, options,
		ethernetLayer,
		ipLayer,
		tcpLayer,
		gopacket.Payload(rawBytes),
	)

	var (
		sockfd int
 		err error
		n int
	)

	//打开RAW socket.
	if sockfd, err = syscall.Socket(syscall.AF_PACKET, syscall.SOCK_RAW, syscall.ETH_P_IP); err != nil {
		fmt.Print("Socket() error:", err.Error())
		return
	}

	defer syscall.Shutdown(sockfd, syscall.SHUT_RDWR)
	//获取本机回路网络信息
	if_info, err := net.InterfaceByName("lo")
	if err != nil {
		fmt.Println("=============================================================================")
		fmt.Println("= Error 2                                                                   =")
		fmt.Println("=============================================================================")
		fmt.Println(err)
	}

	addr := syscall.SockaddrLinklayer{
		Protocol: syscall.ETH_P_IP,
		Ifindex:  if_info.Index,
	}
	syscall.Bind(sockfd,&addr)
	if n,err = syscall.Write(sockfd, buffer.Bytes()); err != nil {
		fmt.Print("Sendto() error: ", err.Error())
		return
	}
	fmt.Printf("Send success! %s",n)
}
